#include "kline_lib.h"
#include <vector>
#include <map>
#include <algorithm>
#include <string>
#include <sstream>
#include <iomanip>
#include <ctime>
#include <iostream>
#include "mouse_pos.h"

/**
 * 这个模拟提供买入卖出的判断依据
 */

// 静态存储K线数据
static std::vector<StockData> kLineData;
static std::string currentStartDate;
static std::string currentEndDate;
static double lastClosePrice=0;
static double g_ma5=0;
static double g_ma10=0;
static double g_ma20=0;
static double g_lastMa5=0;
static double g_lastMa10=0;
static double g_lastMa20=0;
static bool g_isHammerOrStar=false;
static std::map<std::string,size_t> g_arr_index;

// 获取指定日期之前的日期
std::string getDateBefore(const std::string& date, int days) {
    // 将日期字符串转换为tm结构
    std::tm tm = {};
    std::istringstream ss(date);
    ss >> std::get_time(&tm, "%Y-%m-%d");
    
    // 将tm转换为time_t
    std::time_t time = std::mktime(&tm);
    
    // 减去指定的天数
    time -= days * 24 * 60 * 60;
    
    // 将time_t转换回tm
    tm = *std::localtime(&time);
    
    // 将tm转换回字符串
    std::ostringstream result;
    result << std::put_time(&tm, "%Y-%m-%d");
    return result.str();
}

// 初始化K线数据
KLINE_API void initKLineData(const std::vector<StockData>& data) {
    kLineData = data;
    // 初始化索引数据:
    g_arr_index.clear();
    for(size_t i=0;i<kLineData.size();i++)
    {
        const StockData &_data = kLineData[i];
        g_arr_index[_data.trade_date] = i;
    }// END for
}

// 从索引表中取下标
size_t getDateIndex()
{
    // 取下标:
    auto it_end = g_arr_index.lower_bound(currentEndDate);
    if(g_arr_index.end()==it_end)
    {
        // 估计是在数据最后一天之后
        auto iter_right = g_arr_index.rbegin();
        const std::string &str_date_last = iter_right->first;
        if(currentEndDate>str_date_last)
        {
            return g_arr_index.size()-1;
        }
        return 0;
    }
    if(!g_arr_index.contains(currentEndDate))
    {
        --it_end;
    }
    size_t endIndex = it_end->second;
    return endIndex;
}

// 设置日期范围
KLINE_API void setDateRange(const std::string& startDate, const std::string& endDate) {
    currentStartDate = startDate;
    currentEndDate = endDate;
}

// 获取指定日期的K线数据
KLINE_API bool getKLineByDate(const char* date, StockData* klineData) {
    if (!date || !klineData || kLineData.empty()) {
        return false;
    }

    // 查找指定日期的K线数据
    auto it = std::find_if(kLineData.begin(), kLineData.end(),
        [date](const StockData& data) {
            return data.trade_date == date;
        });

    if (it != kLineData.end()) {
        // 找到指定日期的数据，复制到输出参数
        *klineData = *it;
        return true;
    }

    return false;
}

// 获取指定日期范围内的数据
std::vector<StockData> getDataInRange() {
    if (currentStartDate.empty() || currentEndDate.empty()) {
        return kLineData;  // 如果没有设置日期范围，返回所有数据
    }

    
    size_t endIndex = getDateIndex();
    size_t startIndex = endIndex>=90? endIndex - 90:0;
    std::vector<StockData> filteredData(kLineData.begin() + startIndex, kLineData.begin() + endIndex);
    return filteredData;

    // // 先按日期范围筛选
    // for (const auto& data : kLineData) {
    //     if (data.trade_date >= currentStartDate && data.trade_date <= currentEndDate) {
    //         filteredData.push_back(data);
    //     }
    // }
    
    // // 如果数据超过半年(约180天),只保留最近半年的数据
    // if (filteredData.size() > 90) {
    //     filteredData.erase(filteredData.begin(), filteredData.end() - 90);
    // }
    // return filteredData;
}

// 为均线取范围

std::vector<StockData> getDataInRangeForMA() {
    if (currentStartDate.empty() || currentEndDate.empty()) {
        return kLineData;  // 如果没有设置日期范围，返回所有数据
    }

    size_t endIndex = getDateIndex();
    size_t startIndex = endIndex>=300? endIndex - 300:0;
    std::vector<StockData> filteredData(kLineData.begin() + startIndex, kLineData.begin() + endIndex);
    return filteredData;

    // std::vector<StockData> filteredData;
    // // 先按日期范围筛选
    // for (const auto& data : kLineData) {
    //     if (data.trade_date >= getDateBefore(currentStartDate, 41) && data.trade_date <= currentEndDate) {
    //         filteredData.push_back(data);
    //     }
    // }
    
    // // 如果数据超过半年(约180天),只保留最近半年的数据
    // if (filteredData.size() > 90+41) {
    //     filteredData.erase(filteredData.begin(), filteredData.end() - (90+41));
    // }
    // return filteredData;
}

// 绘制空心正方形的函数，以左下角和右上角坐标为参数
void drawHollowSquare(ImDrawList* draw_list, ImVec2 bottomLeft, ImVec2 topRight, float thickness) {
    ImVec2 p1 = bottomLeft;
    ImVec2 p2 = ImVec2(topRight.x, bottomLeft.y);
    ImVec2 p3 = topRight;
    ImVec2 p4 = ImVec2(bottomLeft.x, topRight.y);

    draw_list->AddLine(p1, p2, IM_COL32(255, 0, 0, 255), thickness);
    draw_list->AddLine(p2, p3, IM_COL32(255, 0, 0, 255), thickness);
    draw_list->AddLine(p3, p4, IM_COL32(255, 0, 0, 255), thickness);
    draw_list->AddLine(p4, p1, IM_COL32(255, 0, 0, 255), thickness);
}

// 计算移动平均线
std::vector<float> calculateMA(const std::vector<StockData>& data, int period) {
    std::vector<float> ma;
    if (data.empty() || period <= 0) return ma;

    for (size_t i = 0; i < data.size(); ++i) {
        if (i < period - 1) {
            ma.push_back(0.0f);  // 不足周期的数据填充0
            continue;
        }

        float sum = 0.0f;
        for (int j = 0; j < period; ++j) {
            sum += data[i - j].close;
        }
        ma.push_back(sum / period);
    }
    return ma;
}

// 绘制移动平均线
void drawMA(ImDrawList* drawList, const std::vector<float>& ma, const std::vector<StockData>& rangeData, ImVec2 pos, ImVec2 size, 
            float minPrice, float maxPrice, ImU32 color) {
    if (ma.empty()) return;
    int delta = rangeData.size()-ma.size() ;
    for (size_t i = 0; i < ma.size(); ++i) {
        if (ma[i] == 0.0f) continue;  // 跳过无效数据

        float x = pos.x + (i+delta) * (size.x / rangeData.size());
        float y = pos.y + (maxPrice - ma[i]) * size.y / (maxPrice - minPrice);

        if (i == 0) {
            drawList->AddLine(ImVec2(x, y), ImVec2(x, y), color);
        } else {
            float prevX = pos.x + (i+delta - 1) * (size.x / rangeData.size());
            float prevY = pos.y + (maxPrice - ma[i - 1]) * size.y / (maxPrice - minPrice);
            drawList->AddLine(ImVec2(prevX, prevY), ImVec2(x, y), color);
        }
    }
}

std::vector<float> g_ma5_vector;
std::vector<float> g_ma10_vector;
std::vector<float> g_ma20_vector;
std::vector<float> g_ma120_vector;
std::vector<StockData> g_rangeData;
float g_barWidth;
float g_minPrice;
float g_maxPrice;

KLINE_API void updateKLineData()
{
    // 获取日期范围内的数据
    g_rangeData = getDataInRange();
    std::vector<StockData> rangeDataForMA = getDataInRangeForMA();
    if (g_rangeData.empty()) return;

    g_minPrice = g_rangeData[0].low;
    g_maxPrice = g_rangeData[0].high;

    // 找到最大和最小价格
    for (const auto& data : g_rangeData) {
        if (data.low < g_minPrice) g_minPrice = data.low;
        if (data.high > g_maxPrice) g_maxPrice = data.high;
    }

    // 计算移动平均线
    g_ma5_vector = calculateMA(rangeDataForMA, 5);
    g_ma10_vector = calculateMA(rangeDataForMA, 10);
    g_ma20_vector = calculateMA(rangeDataForMA, 20);
    g_ma120_vector = calculateMA(rangeDataForMA, 120);
    
    const auto& last_data = g_rangeData[g_rangeData.size() - 1];
    lastClosePrice = last_data.close;

    g_ma5 = g_ma5_vector.back();
    g_ma10 = g_ma10_vector.back();
    g_ma20 = g_ma20_vector.back();

    g_lastMa5 = g_ma5_vector[g_ma5_vector.size()-2];
    g_lastMa10 = g_ma10_vector[g_ma10_vector.size()-2];
    g_lastMa20 = g_ma20_vector[g_ma20_vector.size()-2];

    // 判断是十字星还是锤子线
    double delta1 = last_data.close - last_data.open;
    double delta2 = last_data.high - last_data.low;
    g_isHammerOrStar = bool(abs(delta2)/abs(delta1)>3);
}

// 绘制K线
KLINE_API void drawKLine(ImDrawList* drawList, ImVec2 pos, ImVec2 size) {

    g_barWidth = size.x / g_rangeData.size();
    // 绘制K线
    for (size_t i = 0; i < g_rangeData.size(); ++i) {
        const auto& data = g_rangeData[i];
        float x = pos.x + i * g_barWidth;
        float openY = pos.y + (g_maxPrice - data.open) * size.y / (g_maxPrice - g_minPrice);
        float highY = pos.y + (g_maxPrice - data.high) * size.y / (g_maxPrice - g_minPrice);
        float lowY = pos.y + (g_maxPrice - data.low) * size.y / (g_maxPrice - g_minPrice);
        float closeY = pos.y + (g_maxPrice - data.close) * size.y / (g_maxPrice - g_minPrice);

        // 颜色
        auto color = (data.close >= data.open)? IM_COL32(255, 0, 0, 255): IM_COL32(0, 255, 0, 255);

        const float padding_rate = 0.1f;
        const float padding_width = g_barWidth * padding_rate;

        // 绘制
        if (data.close >= data.open) {
            drawHollowSquare(drawList, ImVec2(x+padding_width, openY), ImVec2(x + g_barWidth-padding_width, closeY), 1.0f);
            // 绘制上下影线
            drawList->AddLine(ImVec2(x + g_barWidth / 2, highY), ImVec2(x + g_barWidth / 2, closeY),color);
            drawList->AddLine(ImVec2(x + g_barWidth / 2, openY), ImVec2(x + g_barWidth / 2, lowY),color);
        } else {
            drawList->AddLine(ImVec2(x + g_barWidth / 2, highY), ImVec2(x + g_barWidth / 2, lowY),color);
            drawList->AddRectFilled(ImVec2(x+padding_width, closeY), ImVec2(x + g_barWidth-padding_width, openY), IM_COL32(0, 255, 0, 255));
        }
    }

    // 绘制均线
    drawMA(drawList, g_ma120_vector,g_rangeData, pos, size, g_minPrice, g_maxPrice, IM_COL32(105, 0, 105, 255)); // 120日均线-暗紫色
    drawMA(drawList, g_ma5_vector, g_rangeData, pos, size, g_minPrice, g_maxPrice, IM_COL32(255, 255, 255, 255));  // 5日均线-白色
    drawMA(drawList, g_ma10_vector,g_rangeData, pos, size, g_minPrice, g_maxPrice, IM_COL32(255, 255, 0, 255)); // 10日均线-黄色
    drawMA(drawList, g_ma20_vector,g_rangeData, pos, size, g_minPrice, g_maxPrice, IM_COL32(255, 0, 255, 255)); // 20日均线-紫色
    

    // 绘制文字:收盘价
    char text_close_price[32];
    snprintf(text_close_price, sizeof(text_close_price), "%.2f", lastClosePrice);
    drawList->AddText(ImVec2(pos.x + size.x - 100, pos.y + size.y - 20), IM_COL32(255, 255, 255, 255), text_close_price);

    // 当天的K线:
    StockData todayData;
    if(getKLineByDate(currentEndDate.c_str(), &todayData))
    {
        char text_today_data[128];
        snprintf(text_today_data, sizeof(text_today_data), "今日: %.2f, %.2f, %.2f, %.2f", todayData.open , todayData.high, todayData.low, todayData.close );
        drawList->AddText(ImVec2(pos.x + size.x - 400, pos.y + size.y - 220), IM_COL32(255, 255, 255, 255), text_today_data);
        // BEGIN 星线与锤子线
        // double delta1 = todayData.close - todayData.open;
        // double delta2 = todayData.high - todayData.low;
        // char text_analysis[128];
        // if(abs(delta2)/abs(delta1)>3)
        // {
        //     snprintf(text_analysis, sizeof(text_analysis), "分析: 星线或锤子 收盘价:%.2f", todayData.close);
        //     drawList->AddText(ImVec2(pos.x + size.x - 400, pos.y + size.y - 180), IM_COL32(255, 255, 255, 255), text_analysis);
        // }
        // END 星线与锤子线

        // BEGIN 均线的数据:
        char text_ma[128];
        double ma120 = g_ma120_vector.size()?g_ma120_vector.back():0;
        snprintf(text_ma, sizeof(text_ma), "MA5:%.2f, MA10:%.2f, MA20:%.2f, MA120:%.2f", g_ma5, g_ma10, g_ma20,ma120);
        drawList->AddText(ImVec2(pos.x + size.x - 400, pos.y + size.y - 180), IM_COL32(255, 255, 255, 255), text_ma);
        // END 均线的数据

    }

    // 鼠标坐标:
    int mousePosX = getMousePosX();
    int mousePosY = getMousePosY();
    drawList->AddLine(ImVec2(mousePosX-9990, mousePosY), ImVec2(mousePosX+9990, mousePosY), ImColor(111, 111, 111));
    drawList->AddLine(ImVec2(mousePosX,mousePosY -9999), ImVec2(mousePosX,mousePosY +9999), ImColor(111, 111, 111));
    
}

// 取最后的收盘价
KLINE_API double getLastClosePrice() {
    return lastClosePrice;
}

// 获取5日均线
KLINE_API double getMA5() {
    return g_ma5;
}

// 获取10日均线 
KLINE_API double getMA10() {
    return g_ma10;
}

// 获取20日均线
KLINE_API double getMA20() {
    return g_ma20;
}

// 获取5日均线
KLINE_API double getLastMA5() {
    return g_lastMa5;
}

// 获取10日均线
KLINE_API double getLastMA10() {
    return g_lastMa10;
}

// 获取20日均线
KLINE_API double getLastMA20() {
    return g_lastMa20;
}

// 获取90天内的波动范围 高
KLINE_API double get90DaysHeigh()
{
    return g_maxPrice;
}

// 获取90天内的波动范围 低
KLINE_API double get90DaysLow()
{
    return g_minPrice;
}

// 获取前一天的价格
KLINE_API double getLastDayPrice()
{
    if(g_rangeData.size()>2)
    {
        return g_rangeData[g_rangeData.size()-2].close;
    }
    else
    {
        return 0;
    }
}

// 出现锤子线或星线
KLINE_API bool isHammerOrStar()
{
    return g_isHammerOrStar;
}